const { AbilityBuilder, Ability, subject } = require("@casl/ability");
const { permittedFieldsOf } = require("@casl/ability/extra");
const _ = require("lodash");
const helper = require("../helper/helper");
const model = require("../model/index");
const roleAndActionMap = {
  GET: "read",
  POST: "create",
  PATCH: "update",
  DELETE: "delete",
};
const modelMap = {
  user: model.userModel,
  work: model.workModel,
};
//定义角色
//定义用户角色
function defineRoles(user) {
  //创建AbilityBuilder实例
  const { can, build } = new AbilityBuilder(Ability);
  //判断用户角色
  if (user.role === "admin") {
    //管理员：可以管理所有
    can("manage", "all");
  } else {
    if (user.role === "moderator") {
      //版主：可以管理自己创建的
      can("read", "user", { _id: user._id });
      can("update", "user", ["nickname", "picure"], { _id: user._id });
      //work：创建,查看work, 修改自己的work, 删除自己的work
      can("create", "work", ["title", "desc", "content", "coverImg"]);
      can("read", "work");
      can("update", "work", [
        "title",
        "desc",
        "content",
        "coverImg",
        "isPublic",
        "isHot",
        "isTemplate",
      ]);
      can("delete", "work", { user: user._id });
      can("publish", "work", { user: user._id });
      //channles
      can("read", "work", { user: user._id });
      can("create", "channel", ["name", "id"], { user: user._id });
      can("update", "channel", ["name"], { user: user._id });
      can("delete", "channel", ["name"], { user: user._id });
    } else {
      //普通用户：可以读取自己信息，以及修改nickname与picure
      can("read", "user", { _id: user._id });
      can("update", "user", ["nickname", "picure"], { _id: user._id });
      //work：创建,查看work, 修改自己的work, 删除自己的work
      can("create", "work", ["title", "desc", "content", "coverImg"]);
      can("read", "work", { user: user._id });
      can("update", "work", ["title", "desc", "content", "coverImg", "isPublic", "isTemplate"], {
        user: user._id,
      });
      can("delete", "work", { user: user._id });
      can("publish", "work", { user: user._id });
      //channles
      can("read", "work", { user: user._id });
      can("create", "channel", ["name", "id", "channelUrl"], { user: user._id });
      can("update", "channel", ["name"], { user: user._id });
      can("delete", "channel", ["name"], { user: user._id });
    }
  }
  //返回构建的Ability实例
  return build();
}
module.exports = {
  //校验role
  /**
   *
   * @param {*} modelName 可以是字符串，也可以是casl与model的映射关系
   * @param {*} queryInfo 特殊配置选项，可以自定义action或者查询参数
   * @param {*} key 可以自定义查询的key
   * @returns function
   */
  verifyRole(modelName, queryInfo = {}, key) {
    // 返回一个异步函数
    return async (req, res, next) => {
      try {
        // 获取请求的方法
        const { method } = req;
        // 获取请求的id
        const id =
          req.params?.channelId ||
          req.query?.id ||
          req.body?.id ||
          req.params?.id ||
          req.body?.workId ||
          req.params?.workId;

        let query = {
          _id: id,
        };
        if (queryInfo.channel) {
          query = {
            "channel.id": id,
          };
        }
        console.log(query, "query");

        // 获取请求的方法对应的操作
        const action =
          queryInfo && queryInfo.action
            ? queryInfo.action
            : roleAndActionMap[method];
        // 获取请求的用户信息
        const user = req.info;
        // 如果用户信息不存在，则返回错误信息
        if (!user) {
          return helper.errorMessage({ res, errCode: "UserNotLoginError" });
        }
        const keyModel = key ? key : modelName;
        console.log(modelName);

        // 获取请求的模型
        const model = modelMap[modelName];
        // 初始化权限为false
        let permission = false;
        // 获取用户的角色
        const role = defineRoles(user);
        // 获取用户的角色对应的规则
        const rule = role.relevantRuleFor(action, keyModel);
        const options = { fieldsFrom: (rule) => rule.fields || [] };
        // 如果规则存在且规则中有条件
        if (rule && rule.conditions) {
          const dataRecord = await model.findOne(query).lean();
          // 判断用户是否有权限
          permission = role.can(action, subject(keyModel, dataRecord));
        } else {
          console.log(action, keyModel);

          // 判断用户是否有权限
          permission = role.can(action, keyModel);
        }
        if (rule && rule.fields) {
          const fields = permittedFieldsOf(role, action, keyModel, options);
          if (fields.length > 0) {
            //过滤请求字段
            req.body = _.pick(req.body, fields);
            console.log(req.body, "body");
          }
        }
        // 如果用户没有权限，则返回错误信息
        if (!permission) {
          return helper.errorMessage({ res, errCode: "noPermission" });
        } else {
          // 否则，执行下一个中间件
          next();
        }
      } catch (error) {
        return helper.errorMessage({ res, error });
      }
    };
  },
};
